package com.peanut.huibutie.common;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class HttpInvoker {
    @Resource
    private AppConfig appConfig;

    public <T> OpenApiResult<T> sendGet(String relativeUrl, Map<String, String> param, Class<T> resultDataClass) {
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)//设置连接超时时间
                .readTimeout(20, TimeUnit.SECONDS)//设置读取超时时间
                .build();


        param.put("app_id", String.valueOf(appConfig.getAppId()));
        String sign = MD5SignUtils.getSign(appConfig.getAppSecret(), param);
        param.put("sign", sign);

        StringBuilder queryString = new StringBuilder();
        Iterator<Map.Entry<String, String>> iterator = param.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> next = iterator.next();
            queryString.append(String.format("&%s=%s", next.getKey(), next.getValue()));
        }
        relativeUrl = relativeUrl + "?" + queryString.substring(1);
        log.info("GET请求地址={}", relativeUrl);
        // 创建POST请求
        Request request = new Request.Builder()
                .url(appConfig.getHost() + relativeUrl)
                .get()
                .build();

        // 发送请求并处理响应
        return getResponseResult(client, request, resultDataClass);
    }

    public <T> OpenApiResult sendPost(String relativeUrl, Map param, Class<T> resultDataClass) {
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)//设置连接超时时间
                .readTimeout(20, TimeUnit.SECONDS)//设置读取超时时间
                .build();

        // 创建请求体
        MediaType mediaType = MediaType.parse("application/json");


        param.put("app_id", String.valueOf(appConfig.getAppId()));
        String sign = MD5SignUtils.getSign(appConfig.getAppSecret(), param);
        param.put("sign", sign);

        String requestBody = JSONObject.toJSONString(param);
        log.info("POST请求地址={}，请求数据={}", relativeUrl, requestBody);
        RequestBody body = RequestBody.create(mediaType, requestBody);

        // 创建POST请求
        Request request = new Request.Builder()
                .url(appConfig.getHost() + relativeUrl)
                .post(body)
                .build();

        return getResponseResult(client, request, resultDataClass);
    }

    /**
     * 单独指定 host 的请求
     */
    public <T> OpenApiResult sendPost(String host, String relativeUrl, Map param, Class<T> resultDataClass) {
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)//设置连接超时时间
                .readTimeout(20, TimeUnit.SECONDS)//设置读取超时时间
                .build();
        // 创建请求体
        MediaType mediaType = MediaType.parse("application/json");
        String requestBody = JSONObject.toJSONString(param);
        log.info("POST请求地址={}，请求数据={}", relativeUrl, requestBody);
        RequestBody body = RequestBody.create(mediaType, requestBody);
        // 创建POST请求
        Request request = new Request.Builder()
                .url(host + relativeUrl)
                .post(body)
                .build();
        return getResponseResult(client, request, resultDataClass);
    }

    /**
     * 发送请求并处理响应
     *
     * @param client
     * @param request
     * @param resultDataClass
     * @param <T>
     * @return
     */
    private <T> OpenApiResult<T> getResponseResult(OkHttpClient client, Request request, Class<T> resultDataClass) {
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                String responseBody = response.body().string();
                log.info("响应数据={}", responseBody);
                OpenApiResult rawResult = JSONObject.parseObject(responseBody, OpenApiResult.class);//反序列化出来的是 OpenApiResult<JSON>
                if (rawResult.isSuccess() && StringUtils.isNotBlank(rawResult.getSign())) {
                    JSONObject rawResultData = (JSONObject) rawResult.getData();
                    String sign = MD5SignUtils.getSign(appConfig.getAppSecret(), JSONObject.toJavaObject(rawResultData, Map.class));
                    boolean verifySign = rawResult.getSign().contentEquals(sign);
                    if (!verifySign) {
                        rawResult.setCode(OpenApiErrorCodeEnum.Unauthorized.getCode());
                        rawResult.setMessage("验签失败");
                        return rawResult;
                    }
                }

                OpenApiResult<T> result = rawResult;
                if (!resultDataClass.equals(JSON.class) && rawResult.getData() != null) {
                    T data = ((JSONObject) rawResult.getData()).toJavaObject(resultDataClass);
                    result.setData(data);
                }

                return result;
            } else {
                log.info("Request failed: " + response.code() + " - " + response.message());
            }
        } catch (IOException e) {
            log.error("http请求异常， ", e);
        }
        return null;

    }
}
